﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using Kugar.Core.Data.DBCommon;
using Kugar.Core.ExtMethod;

namespace Kugar.Core.Configuration.Providers
{
    public class DatabaseProvider :MarshalByRefObject, ICustomConfigProvider
    {
        private DbDatabaseHelperBase _helper;
        public DatabaseProvider(DbDatabaseHelperBase helper)
        {
            _helper = helper;
        }

        #region Implementation of IConfigProvider

        public IEnumerable<CustomConfigItem> Load()
        {
            using (_helper)
            {
                var data = _helper.ExecuteDataTable(@"select * from sys_Config
                                                                            ");

                if (data.IsEmptyData())
                {
                    var lst = new List<CustomConfigItem>(data.Rows.Count);

                    foreach (DataRow row in data.Rows)
                    {
                        var dataTypeStr = row["DataType"].ToStringEx().ToLower();

                        if (string.IsNullOrWhiteSpace(dataTypeStr))
                        {
                            continue;
                        }

                        ConfigItemDataType dataType;
                        object value = null;
                        string valueStr = row["Value"].ToStringEx();


                        switch (dataTypeStr)
                        {
                            case "int":
                                value = valueStr.ToInt();
                                dataType= ConfigItemDataType.Int;
                                break;
                            case "decimal":
                                value = valueStr.ToDecimal();
                                dataType=ConfigItemDataType.Decimal;
                                break;
                            case "datatime":
                                value = value.ToDateTime();
                                dataType=ConfigItemDataType.DateTime;
                                break;
                            case "boolean":
                                value = valueStr.ToBool();
                                dataType=ConfigItemDataType.Boolean;
                                break;
                            case "string":
                                value = valueStr;
                                dataType=ConfigItemDataType.String;
                                break;
                            default:
                                if (dataTypeStr.StartsWith("object:"))
                                {
                                    dataType=ConfigItemDataType.Object;

                                    var tempTypeStr = row["DataType"].ToStringEx().Substring(7);

                                    var assList = AppDomain.CurrentDomain.GetAssemblies();

                                    foreach (var assembly in assList)
                                    {
                                        var type= assembly.GetType(tempTypeStr,false);
                                        if (type!=null)
                                        {
                                            value = Convert.ChangeType(valueStr.DeserializeToObject(), type);
                                            break;
                                        }
                                    }

                                }
                                else
                                {
                                    dataType=ConfigItemDataType.Unknow;
                                    value = row["Value"];
                                }
                                break;


                        }

                        var tempItem = new CustomConfigItem(row["Name"].ToStringEx(), dataType, value);
                        

                        lst.Add(tempItem);
                    }

                    return lst;
                }
                else
                {
                    return null;
                }
            }
        }

        public bool Write(IEnumerable<CustomConfigItem> configList)
        {
            const string sqlStr = @"
                                                if exists(select top 1 * from sys_Config where Name=@Name)
                                                begin
                                                    update sys_Config set Value=@value where Name=@Name
                                                end
                                                else
                                                begin
                                                    insert into sys_Config (Name,DataType,Value) value(@Name,@DataType,@Value)
                                                end
                                                ";

            if (configList == null)
            {
                return false;
            }

            try
            {
                using (_helper)
                {
                    //_helper.ExecuteNoQuery("delete from System_Config");

                    var cmd = _helper.CreateCommand();
                    cmd.CommandText = sqlStr;
                    cmd.AddParameters(new ADOCmdParam[]
                    {
                        new ADOCmdParam("@Name",DbType.String, ""), 
                        new ADOCmdParam("@DataType",DbType.String, ""), 
                        new ADOCmdParam("@Value",DbType.String, ""), 
                    });

                    foreach (var item in configList)
                    {
                        if (item.DataType == ConfigItemDataType.Object)
                        {
                            cmd.Parameters.SetValue("@DataType", "object:" + item.Value.GetType().Name);
                            cmd.Parameters.SetValue("@Value", item.Value.SerializeToString());
                        }
                        else
                        {
                            cmd.Parameters.SetValue("@DataType", item.DataType);
                            cmd.Parameters.SetValue("@Value", item.Value.ToStringEx());
                        }

                        cmd.ExecuteNonQuery();
                    }


                }

                return true;
            }
            catch (Exception)
            {
                return false;
            }


        }

        #endregion
    }
}
